package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.cache.LocationBearTypeCache;
import com.arpa.wms.domain.consts.CommonConst;
import com.arpa.wms.domain.dto.LocationBearTypeDTO;
import com.arpa.wms.domain.dto.LocationDTO;
import com.arpa.wms.domain.entity.LocationBearType;
import com.arpa.wms.domain.enums.DeleteFlagEnum;
import com.arpa.wms.domain.enums.StatusEnum;
import com.arpa.wms.domain.vo.LocationBearTypeVO;
import com.arpa.wms.mapper.LocationBearTypeMapper;
import com.arpa.wms.mapper.LocationMapper;
import com.arpa.wms.service.ILocationBearTypeService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 库位承载类型 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-03
 */
@Service
public class LocationBearTypeServiceImpl extends ServiceImpl<LocationBearTypeMapper, LocationBearType> implements ILocationBearTypeService {

    @Resource
    private LocationMapper locationMapper;

    private final PartyCache partyCache;

    private final LocationBearTypeCache locationBearTypeCache;

    public LocationBearTypeServiceImpl(
            LocationBearTypeCache locationBearTypeCache, PartyCache partyCache) {
        this.locationBearTypeCache = locationBearTypeCache;
        this.partyCache = partyCache;
    }
    private static final String LOCATION_BEAR_TYPQ_NAME  ="库位承载类型名称不能重复";


    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(LocationBearType entity) {

        LocationBearTypeDTO query = new LocationBearTypeDTO();
        query.setName(entity.getName());
        query.setGroupCode(UserUtil.getBranchCode());
        //遍历所有数据，使用qieryList方法查询
        List<LocationBearTypeVO> queryRes = queryList(query);
        //判断查询结果是否为空
        if (IterUtil.isNotEmpty(queryRes)) {
            //如果查询的数据不为空则提示
            throw new ServiceException(LOCATION_BEAR_TYPQ_NAME);
        }
        //如果查询的数据是空
        if (StringUtils.isBlank(entity.getCode())) {
            //调用setCode...
            entity.setCode(IdUtil.simpleUUID());
        }
        entity.setGroupCode(UserUtil.getBranchCode());
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            //如果查询创建人是空
            //添加创建人方法
            entity.setCreatedBy(UserUtil.getCode());
            //创建人姓名
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
        }
            //查询修改人是否为空
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            //添加修改人方法
            entity.setModifiedBy(UserUtil.getCode());
            //修改人姓名
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }
        //返回一个添加方法
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(LocationBearType entity) {
        //如果code为空
        if (null == entity.getCode()) {
            //code不能为空
            throw new ServiceException("code不能为空");
        }
        //LocationBearType byCode = getByCode(entity.getCode());
        //if(null == byCode){throw new ServiceException("查询数据失败！");}
        LocationBearTypeDTO query = new LocationBearTypeDTO();
        //获取修改人姓名
        query.setName(entity.getName());
        queryList(query);
        //判断修改人是否为空
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            //添加修改人
            entity.setModifiedBy(UserUtil.getCode());
            //获取修改人姓名
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }
         //根据code刷新缓存
        locationBearTypeCache.flushCache(entity.getCode());
        //修改方法
        return baseMapper.update(entity, new QueryWrapper<LocationBearType>().lambda().eq(LocationBearType::getCode, entity.getCode()).eq(LocationBearType::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 根据code获取详情
     *
     * @param code
     * @return
     */
    @Override
    public LocationBearType getByCode(String code) {
        Map<String, Object> temp = this.locationBearTypeCache.get(code);
        if (MapUtil.isNotEmpty(temp)) {
            return BeanUtil.mapToBean(temp, LocationBearType.class, false);
        }
        return null;
    }

    /**
     * 查询列表
     *
     * @param locationBearTypeDTO
     * @return
     */
    @Override
    public List<LocationBearTypeVO> queryList(LocationBearTypeDTO locationBearTypeDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(locationBearTypeDTO.getSortField())) {
            locationBearTypeDTO.setSortField(CommonUtil.camel2Underline(locationBearTypeDTO.getSortField()));
        }
        List<LocationBearTypeVO> locationBearTypeVOList = baseMapper.queryList(locationBearTypeDTO);
        /*// 添加创建人、修改人翻译
        locationBearTypeVOList.stream().forEach(e -> {
            e.setCreatedByName(partyCache.translate(e.getCreatedBy()));
            e.setModifiedByName(partyCache.translate(e.getModifiedBy()));
        });*/
        return locationBearTypeVOList;
    }

    /**
     * 查询合计,包含总数
     *
     * @param locationBearTypeDTO
     * @return
     */
    @Override
    public LocationBearTypeVO queryListSum(LocationBearTypeDTO locationBearTypeDTO) {
        LocationBearTypeVO locationBearTypeVO = baseMapper.queryListSum(locationBearTypeDTO);
        return locationBearTypeVO;
    }


    /**
     * 删除
     *
     * @param codes
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result deleteByCode(List<String> codes) {

        Map<String, Object> result = this.batchdel(codes);
        Integer success = MapUtil.getInt(result, "success");
        List<String> notDelete = MapUtil.get(result, "notDelete", List.class);
        List<String> InInventory = MapUtil.get(result, "inInventory", List.class);
        int failNum = codes.size() - success;
        StringBuffer buffer = new StringBuffer();
        buffer.append("删除成功" + success + "条；失败" + failNum + "条；");
        if (IterUtil.isNotEmpty(notDelete)) {
            for (String m : notDelete) {
                buffer.append("<br><font color='red'>库位承载类型【" + m + "】删除失败，已被启用过;</font>");
            }
        }
        if (IterUtil.isNotEmpty(InInventory)) {
            for (String m : InInventory) {
                buffer.append("<br><font color='red'>库位承载类型【" + m + "】删除失败，已被占用;</font>");
            }
        }
        return Result.ok(buffer.toString());

    }


    /**
     * 启用状态
     *
     * @param codes
     * @return
     */
    @Override
    public int activeStatus(List<String> codes) {
        int num = this.changeStatus(codes, StatusEnum.ACTIVE, DeleteFlagEnum.NOTDELETE.getCode().toString(),UserUtil.getBranchCode());
        return num;
    }

    /**
     * 停用状态
     *
     * @param codes
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
        public Map<String, Object> unactiveStatus(List<String> codes) {
            Map<String, Object> result = new HashMap<>();
            int num = 0;
        String codesStr = codes.stream().map(c -> StrUtil.wrap(c, "'")).collect(Collectors.joining(","));
        // 获取正使用的承载类型code
        List<String> useCodes = this.baseMapper.queryLocation(codesStr,UserUtil.getBranchCode());
        //可以操作的数据
        List<String> changeCodes = codes.stream().filter(item -> !useCodes.contains(item)).collect(Collectors.toList());
        if (IterUtil.isNotEmpty(changeCodes)) {
            num = this.changeStatus(changeCodes, StatusEnum.UNACTIVE, "",UserUtil.getBranchCode());
            List<String> useName = useCodes.stream().map(info -> {
                return locationBearTypeCache.translate(info);
            }).collect(Collectors.toList());
            result.put("useName", useName);
            this.locationBearTypeCache.flushCacheByGroupCode(UserUtil.getBranchCode());
        }
        result.put("success", num);
        return result;

    }

    /**
     * 验证承载类型
     *
     * @param entity
     * @return
     */
    @Override
    public Result validBearType(LocationBearType entity,String operationMethod) {
        if (StrUtil.isBlank(entity.getName())) {
            return Result.error("承载类型名称不能为空");
        }
        //添加承载类型校验名称
        if (CommonConst.ADD.equals(operationMethod)) {
            int count = this.count(new LambdaQueryWrapper<LocationBearType>().eq(LocationBearType::getName, entity.getName()).eq(LocationBearType::getGroupCode,UserUtil.getBranchCode()));
            if (count > 0) {
                return Result.error(LOCATION_BEAR_TYPQ_NAME);
            }
        }
        if (entity.getSkuQuantity() == null) {
            return Result.error("SKU种数不能为空");
        }
        if (entity.getQuantity() == null) {
            return Result.error("托数不能为空");
        }
        if (entity.getNum() == null) {
            return Result.error("数量不能为空");
        }
        if (entity.getWeight() == null) {
            return Result.error("重量不能为空");
        }
        if (entity.getVolume() == null) {
            return Result.error("体积不能为空");
        }

        return Result.ok();
    }

    /**
     * 变更状态
     *
     * @param codes  标识
     * @param status 状态
     * @return
     */
    private int changeStatus(List<String> codes, StatusEnum status, String deleteFlag,String groupCode) {
        for (String code : codes) {
            this.locationBearTypeCache.flushCache(code);
        }
        String codesStr = codes.stream().map(c -> StrUtil.wrap(c, "'")).collect(Collectors.joining(","));
        return this.baseMapper.changeStatus(codesStr, status.getValue(), deleteFlag,groupCode);
    }

    /**
     * 前台页面库位承载类型下拉数据
     *
     * @return
     */
    @Override
    public List<LocationBearTypeVO> findLocationBearType() {
        List<LocationBearTypeVO> locationBearTypeVOs = this.locationBearTypeCache.getAllByGroupCode(UserUtil.getBranchCode()).stream()
                .map(m -> BeanUtil.mapToBean(m, LocationBearTypeVO.class, false))
                .filter(w -> StrUtil.equals(w.getStatus(), StatusEnum.ACTIVE.getValue()))
                .collect(Collectors.toList());
        return locationBearTypeVOs;
    }

    /**
     * 批量删除
     *
     * @param codes
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Map<String, Object> batchdel(List<String> codes) {
        Map<String, Object> result = new HashMap<>();
        List<LocationBearTypeVO> locationBearTypeVOS = queryByCodes(codes);
        Map<String, String> warehouseMap = locationBearTypeVOS.stream().collect(Collectors.toMap(LocationBearTypeVO::getCode, LocationBearTypeVO::getName));
        //不可删除code
        List<String> notDeleteCodes = locationBearTypeVOS.stream().filter(info -> info.getDeleteFlag().intValue() == DeleteFlagEnum.NOTDELETE.getCode().intValue()).map(info -> {
            return info.getCode();
        }).collect(Collectors.toList());
        List<String> notDeleteName = notDeleteCodes.stream().map(code -> {
            return warehouseMap.get(code);
        }).collect(Collectors.toList());
        result.put("notDelete", notDeleteName);
        List<String> tempCode = codes.stream().filter(code -> !notDeleteCodes.contains(code)).collect(Collectors.toList());
        List<String> tempNoDeleteCode = new ArrayList<>();
        List<String> inventorynotDeleteName = new ArrayList<>();
        tempCode.stream().forEach(code -> {
            LocationDTO locationDTO = new LocationDTO();
            int quantity = 0;
            locationDTO.setBearType(code);
            quantity = locationMapper.queryLocationNum(locationDTO);
            if (quantity != 0) {
                tempNoDeleteCode.add(code);
                inventorynotDeleteName.add(warehouseMap.get(code));
            }
        });
        result.put("inInventory", inventorynotDeleteName);
        int num = 0;
        if (IterUtil.isNotEmpty(tempCode)) {
            List<String> deleteCodes = tempCode.stream().filter(code -> !tempNoDeleteCode.contains(code)).collect(Collectors.toList());
            if (IterUtil.isNotEmpty(deleteCodes)) {
                num = delete(deleteCodes);
            }
        }
        result.put("success", num);
        return result;
    }

    private int delete(List<String> list) {
        int num = 0;
        if (IterUtil.isNotEmpty(list)) {
            for (String code : list) {
                boolean flag = this.update(new UpdateWrapper<LocationBearType>().lambda().eq(LocationBearType::getCode, code).eq(LocationBearType::getGroupCode,UserUtil.getBranchCode())
                        .set(LocationBearType::getDeleted, 1));
                if (flag) {
                    num++;
                    this.locationBearTypeCache.flushCache(code);
                }
            }
        }
        return num;
    }

    @Override
    public List<LocationBearTypeVO> queryByCodes(List<String> codes) {

        return baseMapper.getByCodes(codes,UserUtil.getBranchCode());
    }
}
